#include <cereal/archives/binary.hpp>
#include <cereal/archives/json.hpp>
#include <cereal/types/memory.hpp>
#include <cereal/types/unordered_map.hpp>
#include <enum_example.hpp>
#include <gtest/gtest.h>

TEST(TestEnum, BasicEnumReflection) {
  static_assert(simple_enum::enum_name(Color::Red) == "Red");
  static_assert(simple_enum::enum_name(Color::Green) == "Green");
  static_assert(simple_enum::enum_cast<Color>("Red") == Color::Red);
  static_assert(simple_enum::enum_cast<Color>("xxxxxx").has_value() == false);

  static_assert(simple_enum::enum_name(Texture::Cotton) == "Cotton");
  static_assert(simple_enum::enum_cast<Texture>("Silk") == Texture::Silk);
}

TEST(TestEnum, InnerClassEnum) {
  using SomeEnum = Foo::Bar::InnerEnum;
  static_assert(simple_enum::enum_name(SomeEnum::Bad) == "Bad");
  static_assert(simple_enum::enum_name(SomeEnum::Good) == "Good");
  static_assert(simple_enum::enum_name(SomeEnum::Justsoso) == "Justsoso");
  static_assert(simple_enum::enum_cast<SomeEnum>("xxxxxx").has_value() ==
                false);

  static_assert(simple_enum::enum_cast<SomeEnum>("Bad").has_value());
  static_assert(simple_enum::enum_cast<SomeEnum>("Good").has_value());
  static_assert(simple_enum::enum_cast<SomeEnum>("Justsoso").has_value());
}

TEST(TestEnum, JsonSerialization) {
  std::stringstream ss;
  cereal::JSONOutputArchive archive(ss);
  {
    using SomeEnum = Foo::Bar::InnerEnum;
    std::vector<SomeEnum> vec{SomeEnum::Good, SomeEnum::Bad, SomeEnum::Good};
    archive(vec);
  }
  std::string output_string = ss.str();
  EXPECT_TRUE(output_string.find("Good") != -1);
  EXPECT_TRUE(output_string.find("Bad") != -1);
  EXPECT_TRUE(output_string.find("Justsoso") == -1);
}

TEST(TestEnum, BinarySerialization) {
  std::stringstream ss;
  cereal::BinaryOutputArchive archive(ss);
  {
    using SomeEnum = Foo::Bar::InnerEnum;
    std::vector<SomeEnum> vec(1000, SomeEnum::Good);
    archive(vec);
  }
  std::string output_string = ss.str();
  EXPECT_TRUE(output_string.find("Good") != -1);
  // 由于我们使用string来存储枚举类型，所以其序列化结果是过长的
  EXPECT_TRUE(output_string.length() > 1000 * 4);
}